package com.nextive.weightlogger.activity;

import java.util.Calendar;

import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

import com.nextive.weightlogger.R;
import com.nextive.weightlogger.dao.SettingsDao;
import com.nextive.weightlogger.dao.WeightLogDao;
import com.nextive.weightlogger.dto.Settings;
import com.nextive.weightlogger.dto.WeightEntry;
import com.nextive.weightlogger.ui.WeightPickerDialog;

/**
 * Lets the user enter a new weight entry or edit an existing one.
 * 
 * To start this activity to edit a weight entry set the intent action to
 * {@link Intent#ACTION_EDIT} and set the record id in a {@link Long} extra with
 * the key {@link #INTENT_EXTRA_ID}.
 * 
 * To start it for a new entry simply omit the intent action.
 * 
 * @author Federico Baseggio <fedebaseggio@gmail.com>
 */
public class LogWeightActivity extends BaseActivity {
	public static final String INTENT_EXTRA_ID = "INTENT_EXTRA_ID";
	private static final int MIN_WEIGHT_GRAMS = 0;
	private static final int MAX_WEIGHT_GRAMS = 350000;
	
	// Widgets
	private TextView dateField;
	private TextView timeField;
	private TextView weightField;

	private WeightEntry weightEntry;
	private WeightLogDao dao;
	private Settings settings;
	private SettingsDao settingsDao;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.log_weight);

		dateField = (TextView) findViewById(R.id.date_field);
		timeField = (TextView) findViewById(R.id.time_field);
		weightField = (TextView) findViewById(R.id.weight_field);

		LinearLayout dateLayout = (LinearLayout) findViewById(R.id.date_layout);
		dateLayout.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				promptForDate();
			}
		});

		LinearLayout timeLayout = (LinearLayout) findViewById(R.id.time_layout);
		timeLayout.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				promptForTime();
			}
		});

		LinearLayout weightLayout = (LinearLayout) findViewById(R.id.weight_layout);
		weightLayout.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				promptForWeight();
			}
		});
		
		Button saveButton = (Button) findViewById(R.id.weight_save);
		saveButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				saveEntry();
			}
		});
		
		dao = new WeightLogDao(this);
		settingsDao = new SettingsDao(this);
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		settings = settingsDao.readSettings();
		Long id = null;
		if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
			// Edit an existing weight entry
			id = getIntent().getExtras().getLong(INTENT_EXTRA_ID);
			weightEntry = dao.read(id);
		}
		else
		{
			// Create a new weight entry
			if (weightEntry == null)
			{
				weightEntry = new WeightEntry();
				weightEntry.setDateTime(Calendar.getInstance());
				WeightEntry lastEntry = dao.readMostRecent();
				if (lastEntry != null)
				{
					weightEntry.setWeightGrams(lastEntry.getWeightGrams());
				}
				promptForWeight();
			}
		}
		updateDisplay();
	}
	
	/**
	 * Saves the current entry.
	 */
	private void saveEntry() {
		if (weightEntry.getId() == null) {
			if (dao.add(weightEntry))
			{
				Toast.makeText(this, R.string.entry_added, Toast.LENGTH_SHORT)
					.show();
			}
		} else {
			if (dao.update(weightEntry) == 1)
			{
				Toast.makeText(this, R.string.entry_saved, Toast.LENGTH_SHORT)
					.show();
			}
		}
		finish();
	}

	/**
	 * Shows a date picker dialog to let the user pick the date of his weight
	 * entry.
	 */
	private void promptForDate() {
		DatePickerDialog.OnDateSetListener onDateSetListener = 
			new DatePickerDialog.OnDateSetListener() {
			@Override
			public void onDateSet(DatePicker view, int year, int monthOfYear,
					int dayOfMonth) {
				weightEntry.getDateTime().set(Calendar.YEAR, year);
				weightEntry.getDateTime().set(Calendar.MONTH, monthOfYear);
				weightEntry.getDateTime()
						.set(Calendar.DAY_OF_MONTH, dayOfMonth);
				updateDisplay();
			}
		};
		int year = weightEntry.getDateTime().get(Calendar.YEAR);
		int month = weightEntry.getDateTime().get(Calendar.MONTH);
		int day = weightEntry.getDateTime().get(Calendar.DAY_OF_MONTH);
		DatePickerDialog dialog = new DatePickerDialog(this, onDateSetListener,
				year, month, day);
		dialog.show();
	}

	/**
	 * Shows a time picker dialog to let the user pick the time of his weight
	 * entry.
	 */
	private void promptForTime() {
		TimePickerDialog.OnTimeSetListener onTimeSetListener = 
			new TimePickerDialog.OnTimeSetListener() {
			@Override
			public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
				weightEntry.getDateTime().set(Calendar.HOUR_OF_DAY, hourOfDay);
				weightEntry.getDateTime().set(Calendar.MINUTE, minute);
				updateDisplay();
			}
		};
		int hour = weightEntry.getDateTime().get(Calendar.HOUR_OF_DAY);
		int minute = weightEntry.getDateTime().get(Calendar.MINUTE);
		TimePickerDialog dialog = new TimePickerDialog(this, onTimeSetListener,
				hour, minute, false);
		dialog.show();
	}

	/**
	 * Shows a weight picker dialog to let the user pick the weight value of his weight
	 * entry.
	 */
	private void promptForWeight() {
		WeightPickerDialog.OnWeightSetListener onWeightSetListener = 
			new WeightPickerDialog.OnWeightSetListener() {
			@Override
			public void onWeightSet(float weight) {
				weightEntry.setWeight(weight, settings.getUnit());
				updateDisplay();
			}
		};

		int minValue = (int) settings.getUnit()
				.valueFromGrams(MIN_WEIGHT_GRAMS);
		int maxValue = (int) settings.getUnit()
				.valueFromGrams(MAX_WEIGHT_GRAMS);
		Float currentValue = weightEntry.getWeight(settings.getUnit());

		WeightPickerDialog dialog = new WeightPickerDialog(this,
				onWeightSetListener, currentValue, minValue, maxValue);
		dialog.show();
	}

	/**
	 * Updates the text of the widgets based on the {@link #weightEntry}
	 * values.
	 */
	private void updateDisplay() {
		if (weightEntry.getDateTime() == null) {
			dateField.setText(R.string.data_not_set);
			timeField.setText(R.string.data_not_set);
		} else {
			dateField.setText(weightEntry.getDateForDisplay());
			timeField.setText(weightEntry.getTimeForDisplay());
		}
		if (weightEntry.getWeightGrams() == null) {
			weightField.setText(R.string.data_not_set);
		} else {
			weightField.setText(weightEntry.getWeightForDisplay(settings
					.getUnit()));
		}

	}
}
